package danran.dbapi.core.handler;

import danran.dbapi.core.log.Logger;
import danran.dbapi.core.node.MixedSqlNode;
import danran.dbapi.core.node.SqlNode;
import danran.dbapi.core.node.TextSqlNode;
import org.dom4j.*;
import org.dom4j.tree.DefaultElement;
import org.dom4j.tree.DefaultText;
import org.w3c.dom.Text;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class XmlParser {

    private static final Logger log = Logger.getInstance(XmlParser.class);

    static Map<String, TagHandler> nodeHandlers = new HashMap<String, TagHandler>() {
        {
            put("foreach", new ForeachHandler());
            put("if", new IfHandler());
            put("trim", new TrimHandler());
            put("where", new WhereHandler());
            put("set", new SetHandler());
        }
    };

    public static void addTagHandler(String handlerName, TagHandler handler) {
        nodeHandlers.put(handlerName, handler);
    }

    //将xml内容解析成sqlNode类型
    public static SqlNode parseXml2SqlNode(String text) {
        log.info("解析xml-sql: " + text);
        Document document;
        try {
            // 获得xml document对象
            document = DocumentHelper.parseText(text);
        } catch (DocumentException e) {
            throw new RuntimeException(e.getMessage());
        }
        // 获得根元素
        Element rootElement = document.getRootElement();
        List<SqlNode> contents = parseElement(rootElement);
        return new MixedSqlNode(contents);
    }

    //解析单个标签的子内容，转化成sqlNode list
    public static List<SqlNode> parseElement(Element element) {
        List<SqlNode> nodes = new ArrayList<>();
        List<Object> children = element.content();
        for (Object node : children) {
            if (node instanceof DefaultText) {
                String innerSql = ((DefaultText) node).getText();
                log.info(innerSql);

                TextSqlNode textSqlNode = new TextSqlNode(innerSql);
                nodes.add(textSqlNode);
            } else if (node instanceof Element) {
                String nodeName = ((Element) node).getName();
                // 根据不同的标签选择不同的TagHandler
                TagHandler handler = nodeHandlers.get(nodeName.toLowerCase());
                if (handler == null) {
                    throw new RuntimeException("Tag not supported! You can implement " +
                            "an interface named TagHandler and use addTagHandler(String handlerName, TagHandler handler) " +
                            "to add your handler to support this tag.");
                }
                //内部递归调用此方法
                handler.handle((Element) node, nodes);
            }
        }
        return nodes;
    }

    public static void main(String[] args) {
        parseXml2SqlNode("<a>111<if test='true'>222<if test='true'>333</if>444<foreach collection='list' open='(' close=')' separator=',' item='item'>fff</foreach></if>555</a>");
    }
}
